﻿using Canteen.Core.Common;
using Canteen.Core.Models;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading.Tasks;
using Dapper;
using System.Data;

namespace Canteen.Core.Services
{
    public class ShopOrderImplement : IShopOrderService
    {
        private readonly CanteenDbContext dbContext;
        private readonly IGetting getting;

        public ShopOrderImplement(CanteenDbContext dbContext, IGetting getting)
        {
            this.dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
            this.getting = getting ?? throw new ArgumentNullException(nameof(getting));
        }

        public async Task<bool> CreateShopOrder(ShopOrderSubmitDTO dto)
        {
            //1 开启事务
            using var tran = dbContext.Database.BeginTransaction();
            try
            {
                User user = await dbContext.Users.Where(u => u.Id == dto.UserId && u.Code == dto.UserCode).FirstOrDefaultAsync();
                if (user is null) throw new Exception("用户不存在");
                decimal price = dto.Products.Sum(p => p.Price * p.Number);//订单金额
                if (user.Wallet < price) throw new Exception("用户余额不足");
                user.Wallet -= price;
                ShopOrder order = new ShopOrder()
                {
                    OrderNo = getting.OrderNo,
                    UserId = dto.UserId,
                    StoreId = dto.StoreId,
                    Status = 1,
                    PayStatus = 1,
                    PayMode = dto.PayMode,
                    PayTime = DateTime.Now,
                    FinishTime = DateTime.Now,
                    Price = price,
                    Discount = dto.Discount,
                    TotalPrice = price + dto.Discount
                };
                order.ShopOrderProductList = dto.Products.Select(p => new ShopOrderProducts()
                {
                    ShopOrderId = order.Id,
                    ProductId = p.ProductId,
                    Number = p.Number,
                    Price = p.Price
                }).ToList();
                await dbContext.ShopOrders.AddAsync(order);
                if (await dbContext.SaveChangesAsync() > 0)
                {
                    await tran.CommitAsync();//提交事务
                    return true;
                }
                else throw new Exception("订单保存失败");
            }
            // 数据库抛出异常
            catch (SqlException)
            {
                await tran.RollbackAsync();
                throw new Exception("订单异常，请联系管理员");
            }
            catch (Exception e)
            {
                await tran.RollbackAsync();
                throw new Exception(e.Message);
            }
        }
        public async Task<dynamic> SelectShopOrderById(int id)
        {
            var x = await dbContext.ShopOrders.Where(s => s.IsDel == false && s.Id == id)
                .Include(s => s.User)
                .Include(s => s.Store)
                .Include(s => s.ShopOrderProductList)
                    .ThenInclude(sp => sp.Product)
                .FirstOrDefaultAsync();
            return new
            {
                x.Id,
                x.OrderNo,
                x.Status,
                x.PayStatus,
                x.PayMode,
                x.PayTime,
                x.FinishTime,
                x.Price,
                x.Discount,
                x.TotalPrice,
                x.CreateTime,
                x.UpdateTime,
                User = new
                {
                    x.User.Id,
                    x.User.Code,
                    x.User.Name,
                    x.User.Phone
                },
                Store = new
                {
                    x.Store.Id,
                    x.Store.Name
                },
                ProductList = x.ShopOrderProductList.Select(p => new
                {
                    p.Id,
                    p.Number,
                    p.Price,
                    p.Product.Name,
                    p.Product.Type,
                    p.Product.VitaminA,
                    p.Product.VitaminB,
                    p.Product.VitaminC
                }).ToList()
            };
        }
        public async Task<bool> DeleteShopOrder(int id)
        {
            var shopOrder = await dbContext.ShopOrders.SingleOrDefaultAsync(l => l.Id == id);
            shopOrder.IsDel = true;
            return await dbContext.SaveChangesAsync() > 0;
        }



        public async Task<dynamic> GetPageList(ShopOrderPageParameters parameters)
        {
            var query = dbContext.ShopOrders.Where(s => s.IsDel == false)
                .Include(s => s.User)
                .Include(s => s.Store)
                .Include(s => s.ShopOrderProductList)
                    .ThenInclude(sp => sp.Product)
                .AsQueryable();
            if (parameters.StoreId != null && parameters.StoreId > 0)
            {
                query = query.Where(m => m.StoreId.Equals(parameters.StoreId));
            }
            if (parameters.UserId != null && parameters.UserId > 0)
            {
                query = query.Where(m => m.UserId.Equals(parameters.UserId));
            }
            if (!string.IsNullOrWhiteSpace(parameters.OrderNo))
            {
                query = query.Where(m => m.OrderNo.Contains(parameters.OrderNo.Trim()));
            }
            if (!string.IsNullOrWhiteSpace(parameters.UserName))
            {
                query = query.Where(m => m.User.Name.Contains(parameters.UserName.Trim()));
            }
            if (!string.IsNullOrWhiteSpace(parameters.UserPhone))
            {
                query = query.Where(m => m.User.Phone.Equals(parameters.UserPhone.Trim()));
            }
            if (!string.IsNullOrWhiteSpace(parameters.StoreName))
            {
                query = query.Where(m => m.Store.Name.Contains(parameters.StoreName.Trim()));
            }
            var page = await PageList<ShopOrder>.CreateAsync(query.OrderByDescending(o => o.CreateTime),
                parameters.Current,
                parameters.PageSize);
            var result = page.List.Select(x => new
            {
                x.Id,
                x.OrderNo,
                x.Status,
                x.PayStatus,
                x.PayMode,
                x.PayTime,
                x.FinishTime,
                x.Price,
                x.Discount,
                x.TotalPrice,
                x.CreateTime,
                x.UpdateTime,
                User = new
                {
                    x.User.Id,
                    x.User.Code,
                    x.User.Name,
                    x.User.Phone
                },
                Store = new
                {
                    x.Store.Id,
                    x.Store.Name
                },
                ProductList = x.ShopOrderProductList.Select(p => new
                {
                    p.Id,
                    p.Number,
                    p.Price,
                    p.Product.Name,
                    p.Product.Type,
                    p.Product.VitaminA,
                    p.Product.VitaminB,
                    p.Product.VitaminC
                }).ToList()
            }).ToList();
            return new
            {
                page.Current,
                page.Total,
                page.PageSize,
                page.PageTotal,
                List = result
            };
        }

        public async Task<HomeEchartDTO> GetHomeEchart(int UserId)
        {
            using var db = dbContext.Database.GetDbConnection();
            using var mul = await db.QueryMultipleAsync("[HomeEchart]", new { UserId }, commandType: CommandType.StoredProcedure);

            var HE1 = await mul.ReadFirstAsync<HomeEchart1DTO>();
            var HE2 = (await mul.ReadAsync<HomeEchart2DTO>()).ToList();
            var HE3 = (await mul.ReadAsync<HomeEchart3DTO>()).ToList();
            return new HomeEchartDTO()
            {
                HE1 = HE1,
                HE2 = HE2,
                HE3 = HE3
            };
        }

        
    }
}